use crate::error::AppError;
use crate::models::{Claims, Token, UserCreate, UserLogin, UserResponse};
use axum::{
    extract::State,
    http::StatusCode,
    response::{IntoResponse, Json},
};
use tracing::debug;

pub async fn register(
    State(state): State<crate::AppState>,
    Json(user_data): Json<UserCreate>,
) -> Result<impl IntoResponse, AppError> {
    let user = state.auth_service.create_user(&user_data, false).await?;
    let response = UserResponse::from(user);
    Ok((StatusCode::CREATED, Json(response)))
}

pub async fn register_admin(
    State(state): State<crate::AppState>,
    Json(user_data): Json<UserCreate>,
) -> Result<impl IntoResponse, AppError> {
    // Check if any admin users already exist
    let existing_admins = state.auth_service.list_users(1, 1, None).await?.0;
    let has_admin = existing_admins.iter().any(|u| u.is_admin);

    if has_admin {
        return Err(AppError::Validation(
            "Admin user already exists".to_string(),
        ));
    }

    let user = state.auth_service.create_user(&user_data, true).await?;
    let response = UserResponse::from(user);
    Ok((StatusCode::CREATED, Json(response)))
}

pub async fn login(
    State(state): State<crate::AppState>,
    Json(credentials): Json<UserLogin>,
) -> Result<impl IntoResponse, AppError> {
    debug!("Received login request for user: {}", credentials.email);
    let token = state.auth_service.login_user(&credentials).await?;
    let response = Token {
        access_token: token,
        token_type: "bearer".to_string(),
    };
    Ok(Json(response))
}

pub async fn user_info(
    claims: Claims,
    State(state): State<crate::AppState>,
) -> Result<impl IntoResponse, AppError> {
    let user = state.auth_service.get_user_by_email(&claims.sub).await?;
    let response = UserResponse::from(user);
    Ok(Json(response))
}
